package ServerOperation;

import java.io.File;
import java.sql.Connection;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

import org.jfree.chart.JFreeChart;

import Controllers.GlobalData;
import Controllers.GenericToolsForController.PDFfile;
import Entity.Request;

public class ReportBuilder {
private Connection conn;

	
	public ReportBuilder(java.sql.Connection connection)
	{
		conn = connection;
	}
	
	
	public boolean createActivityReport(String filename, Date startDate, Date endDate)
	{
		DBStatistical statisticalHandler = (new DBStatistical(conn));
		Object[] dataArr = statisticalHandler.activityReportData(startDate, endDate);
		Float numberOfCloseRequest = new Float((Integer)dataArr[0]);
		Float numberOfOpenRequest = new Float((Integer)dataArr[1]);
		Float numberOfSuspendeRequest = new Float((Integer)dataArr[2]);
		Float numberOfRejectedRequest = new Float((Integer)dataArr[3]);
		Map<Integer,Double> map = (Map<Integer, Double>)dataArr[4];

	
		///////////// fictitious values ////////////////
	/*	
		numberOfCloseRequest =  (float) 100;
		numberOfOpenRequest = (float) 50;
		numberOfSuspendeRequest= (float) 200;
		numberOfRejectedRequest = (float) 20;
		for(int i =0 ; i<100 ; i++)
		{
			map.put(new Integer(i),new Integer(5));
		}
		for(int i =100 ; i<200 ; i++)
		{
			map.put(new Integer(i),new Integer(i));
		}
		for(int i =200 ; i<300 ; i++)
		{
			map.put(new Integer(i),new Integer(50));
		}
		map.put(new Integer(300),new Integer(100));
*/
		/////////////////////////////////////////////
		
		ReportPDFWriter writer = new ReportPDFWriter(filename);
		writer.addLogo();
		 Map<String, Float> pieMap = new  HashMap<String,Float>() ;
		 String startStr = new SimpleDateFormat("yyyy-MM-dd").format(startDate);
			String endStr = new SimpleDateFormat("yyyy-MM-dd").format(endDate);
		writer.writeTitle("Periodic Activity Report For Period:\n "+startStr +" - "+endStr +"\n\n");
		
		writer.writeUnderline("Number of closed requests for this period: ");
		writer.write(numberOfCloseRequest+" ");
		pieMap.put("CLOSED", numberOfCloseRequest);
		System.out.println("CLOSED "+numberOfCloseRequest);
		
		writer.writeUnderline("Number of open requests for this period: ");
		writer.write(numberOfOpenRequest+" ");
		pieMap.put("OPEN", numberOfOpenRequest);
		System.out.println("OPEN "+numberOfOpenRequest);

		writer.writeUnderline("Number of suspended requests for this period: ");
		writer.write(numberOfSuspendeRequest+" ");
		pieMap.put("SUSPEND", numberOfSuspendeRequest);
		System.out.println("SUSPEND "+numberOfSuspendeRequest);

		writer.writeUnderline("Number of rejected requests for this period: ");
		writer.write(numberOfRejectedRequest+" ");
		pieMap.put("REJECTED", numberOfRejectedRequest);
		System.out.println("REJECTED "+numberOfRejectedRequest);
		
		JFreeChart chart = writer.createPieChartForReport( pieMap,"Distribution of requests by status");
		writer.write(chart,350,350,100,100);
		writer.newPage();
		writer.writeTitle("Summery Of Work days spent on requests this period:\n\n ");
		writer.writeUnderline("Total number of days spent this month: ");
		writer.write(sumDouble(map)+"\n");
		writer.writeUnderline("Max number of days for single request: ");
		writer.write(maxDouble(map)+"\n\n");
		writer.writeUnderline("Avarage number of days per  request: ");
		writer.write(avaregeDouble(map)+"\n\n");
		writer.writeUnderline("Median number of days per  request: ");
		writer.write(median(map)+"\n\n");
		writer.writeUnderline("Deviation of number of days per  request: ");
		writer.write(deviation(map)+"\n\n");
// building destribution map
		double step = (maxDouble(map)/10);
		Map<String,Float> destriMap = new HashMap<String,Float>();
		Double start = new Double(0);
		Double end = new Double(step);
		for (int i=0 ; i<10 ; i++ )
		{
			destriMap.put(start+" - "+end, (float) countInRangeDouble(map, start, end));
			start += step;
			end += step;
			
		}
		JFreeChart barChart =  writer.createBarChartForReport( destriMap,"Distribution of work days per request");
		writer.write(barChart,350,350,100,100);

		
		
		writer.close();
		return true;

		
	}
	
	public boolean createOperationReport(String filename, Date startDate, Date endDate)
	{
		DBStatistical statisticalHandler = (new DBStatistical(conn));
		Object[] dataArr = statisticalHandler.operationReportData(startDate, endDate);
		float  totalNumberExtensionDenial = (float)statisticalHandler.getNumberOfDenyExetanction(startDate, endDate);
		float numberOfAprrovalExetensios = (Integer)dataArr[0];
		Float numberOfEnyExetensios = new Float((Integer) dataArr[1]);
		Map<Integer,Integer> fromStep2 = (Map<Integer, Integer>)dataArr[2];
		Map<Integer,Integer> fromStep4 = (Map<Integer, Integer>)dataArr[3];
		 

	
		///////////// fictitious values ////////////////
		/*
		numberOfAprrovalExetensios = 100;
		numberOfEnyExetensios =  (float) 200.0;
		for(int i =0 ; i<100 ; i++)
		{
			fromStep2.put(new Integer(i),new Integer(i));
		}
		for(int i =100 ; i<200 ; i++)
		{
			fromStep4.put(new Integer(i),new Integer(i));
		}
		
        */
		/////////////////////////////////////////////
		
		ReportPDFWriter writer = new ReportPDFWriter(filename);
		writer.addLogo();
		 Map<String,Float> pieMap = new  HashMap<String,Float>() ;
		 String startStr = new SimpleDateFormat("yyyy-MM-dd").format(startDate);
			String endStr = new SimpleDateFormat("yyyy-MM-dd").format(endDate);
		writer.writeTitle("Periodic Operation Report For Period:\n "+startStr +" - "+endStr +"\n\n");
		
		writer.writeUnderline("Total number of time extensions Approved: ");
		writer.write(numberOfAprrovalExetensios+" ");
		pieMap.put("Approved", numberOfAprrovalExetensios);
		
		writer.writeUnderline("Total number of time extensions Approved: ");
		writer.write(totalNumberExtensionDenial+" ");
		pieMap.put("Denied", totalNumberExtensionDenial);
		
		writer.writeUnderline("Total length (in days) of time extension: ");
		writer.write(numberOfEnyExetensios+"");
	
		
		JFreeChart chart = writer.createPieChartForReport( pieMap,"Distribution of time extensions by status");
		writer.write(chart,350,350,100,100);
		
		writer.newPage();
		writer.writeTitle( "                     Summery Of Work days spent on \n                  requests going back to Evaluation step:\n ");
		writer.writeUnderline("total days added by in this step: ");
		writer.write(sum(fromStep2)+"\n");
		writer.writeUnderline("Max number of days  of days going back to Evaluation step: ");
		writer.write(max(fromStep2)+"\n\n");
		writer.writeUnderline("Avarage number of days going back to Evaluation step: ");
		writer.write(avarege(fromStep2)+"\n\n");
		writer.writeUnderline("Median number of days going back to Evaluation step:");
		writer.write(medianInt(fromStep2)+"\n\n");
		writer.writeUnderline("Deviation number of days going back to Evaluation step:");
		writer.write(deviationInt(fromStep2)+"\n\n");
// building destribution map
		float step =  (max(fromStep2)/10);
		Map<String,Float> destriMap2 = new HashMap<String,Float>();
		Float start2 = new Float(0);
		Float end2 = new Float(step);
		for (int i=0 ; i<10 ; i++ )
		{
			destriMap2.put(start2+" - "+end2, countInRange(fromStep2, start2, end2));
			start2 += step;
			end2 += step;
			
		}
		JFreeChart barChart2 =  writer.createBarChartForReport( destriMap2,"Distribution of work days per request in Evaluation");
		writer.write(barChart2,350,350,100,100);


		writer.newPage();
		writer.writeTitle("                     Summery Of Work days spent on \n                  requests going back to Execution step: \n");
		writer.writeUnderline("total days added by in this step: ");
		writer.write(sum(fromStep4)+"\n");
		writer.writeUnderline("Max number of days  of days going back to Evaluation step: ");
		writer.write(max(fromStep4)+"\n\n");
		writer.writeUnderline("Avarage number of days going back to Evaluation step: ");
		writer.write(avarege(fromStep4)+"\n\n");
		writer.writeUnderline("Median number of days going back to Evaluation step:");
		writer.write(medianInt(fromStep4)+"\n\n");
		writer.writeUnderline("Deviation number of days going back to Evaluation step:");
		writer.write(deviationInt(fromStep4)+"\n\n");
// building destribution map
		float step4 = (float) (max(fromStep2)/10);
		Map<String,Float> destriMap4 = new HashMap<String,Float>();
		Float start4 = new Float(0);
		Float end4 = new Float(step);
		for (int i=0 ; i<10 ; i++ )
		{
			destriMap4.put(start4+" - "+end4, countInRange(fromStep2, start4, end4));
			start4 += step;
			end4 += step;
			
		}
		JFreeChart barChart4 =  writer.createBarChartForReport( destriMap4,"Distribution of work days per request in Execution");
		writer.write(barChart4,350,350,100,100);
		
		writer.close();
		return true;

		
	}
	
	


	public boolean createDelaysReport(String filename, Date startDate, Date endDate)
	{
	DBStatistical statisticalHandler = (new DBStatistical(conn));
	Map<Integer, String[]> NumbersOfDelayAndNumbersOfWorkingDaysForAllRequests = statisticalHandler.getNumbersOfDelayAndNumbersOfWorkingDaysForAllRequests(startDate, endDate);
	//mp.put(reqId, new String[]{countDeley,amountDays,infoName});
	 Map<String,Float> pieMap = new  HashMap<String,Float>() ;
	float totalNumberExtension =0;
	float totalAmountExtension=0;
	 Map <String, Float> perInfoSystem = new HashMap<String, Float>();

	for (String[] strArr:NumbersOfDelayAndNumbersOfWorkingDaysForAllRequests.values() )
	{
		totalNumberExtension+= new Float(strArr[0]);
		totalAmountExtension+= new Float(strArr[1]);
		if ( strArr[2] != null && strArr[2] instanceof String)
		{
			String infoSystem =  (String)strArr[2];
			if (perInfoSystem.containsKey(infoSystem))
			{
				perInfoSystem.put(infoSystem, perInfoSystem.get(infoSystem)+1);
			}
			else
			{
				perInfoSystem.put(infoSystem, new Float(1));
			}
		}
		

	}
	 


	///////////// fictitious values ////////////////
	
	

	/////////////////////////////////////////////
	
	ReportPDFWriter writer = new ReportPDFWriter(filename);
	writer.addLogo();
	 String startStr = new SimpleDateFormat("yyyy-MM-dd").format(startDate);
		String endStr = new SimpleDateFormat("yyyy-MM-dd").format(endDate);
	writer.writeTitle("Periodic Delay Report For Period:\n "+startStr +" - "+endStr +"\n\n");
	writer.write("This report summs all request that time delays:");

	writer.writeUnderline("Total number of time Delays: ");
	writer.write(totalNumberExtension+"");
	pieMap.put("Number Of Time Extensions", totalNumberExtension);
	
	writer.writeUnderline("Total length (in days) of time extension: ");
	writer.write(totalAmountExtension+"");

	writer.newPage();
	writer.writeTitle( "                     Summery Of  delays  \n               By Info Systems :\n ");
	int i=0;
	for(String infoSystem : perInfoSystem.keySet())
	{
		writer.writeUnderline(i+"). Info System "+infoSystem);
		writer.write(perInfoSystem.get(infoSystem)+"");
	}
	JFreeChart chart = writer.createPieChartForReport( perInfoSystem,"Distribution of time extensions by Info Systems");
	writer.write(chart,350,350,100,100);
	
	writer.close();
	return true;

	
}
	
	
	
	public float sum(Map<Integer, Integer> map)
	{
		float sum=0;
		for (Integer num : map.values())
		{
			if (num>0 ) 
			{
				sum+=num;
			}
			else
			{
				System.out.println("Negative days in function sum");
			}
		}
		return sum;
	}
	
	public float avarege(Map<Integer, Integer> map)
	{
		float avarege = sum(map)/(map.size());
		return avarege;
	}
	
	public double median(Map<Integer, Double> map)
	{
		if (map.size() >0 )
		{
			TreeMap<Integer,Double> srtdMap = new TreeMap<Integer,Double>(map);
			Double[] sortedArray =  new Double[srtdMap.values().size()] ;
			sortedArray=map.values().toArray(sortedArray);
			Arrays.sort(sortedArray);
			Double median;
			if (sortedArray.length%2 == 0) 
			{
				median = sortedArray[(sortedArray.length/2)];
			}
			else
				median = sortedArray[(sortedArray.length+1)/2];
	
			
			return median;
		}
		 return 0;
	}
	
	public double medianInt(Map<Integer, Integer> map)
	{
		if (map.size() >0 )
		{
			TreeMap<Integer,Integer> srtdMap = new TreeMap<Integer,Integer>(map);
			Double[] sortedArray =  new Double[srtdMap.values().size()] ;
			sortedArray=map.values().toArray(sortedArray);
			Arrays.sort(sortedArray);
			Double median;
			if (sortedArray.length%2 == 0) 
			{
				median = sortedArray[(sortedArray.length/2)];
			}
			else
				median = sortedArray[(sortedArray.length+1)/2];
	
			
			return median;
		}
		 return 0;
	}
	
	public float max(Map<Integer, Integer> map)
	{
		if (map.size() >0)
		{
		float max = 0;
		for (int val: map.values())
		{
			if (val>max) max=val;
		}
		return max;
		}
		return 0;
	}
	
	public float countInRange(Map<Integer, Integer> map,float start,float end)
	{
		Float counter = new Float(0);
		for (Integer num :map.values() )
		{
			if (num>=start && num<=end) counter++;
		}
		return counter;
	}
	
	

	public double maxDouble(Map<Integer, Double> map)
	{
		if (map.size() >0)
		{
			double max = 0;
		for (double val: map.values())
		{
			if (val>max) max=val;
		}
		return max;
		}
		return 0;
	}
	
	public double countInRangeDouble(Map<Integer, Double> map,Double start,Double end)
	{
		Double counter = new Double(0);
		for (Double num :map.values() )
		{
			if (num>=start && num<=end) counter++;
		}
		return counter;
	}
	
	
	public double sumDouble(Map<Integer, Double> map)
	{
		double sum=0;
		for (Double num : map.values())
		{
			if (num>0 ) 
			{
				sum+=num;
			}
			else
			{
				System.out.println("Negative days in function sum");
			}
		}
		return sum;
	}
	
	public double avaregeDouble(Map<Integer, Double> map)
	{
		double avarege = sumDouble(map)/(map.size());
		return avarege;
	}
	

	
	public static void main(String[] args) 
	{
		DBHandler dh  = DBHandler.getInstance();
		ReportBuilder rb = new ReportBuilder(dh.getConn());
		Date start = new Date(new Date().getTime() - 14*1000*24*60*60);
		Date end = new Date(new Date().getTime() + 16*1000*24*60*60);
		rb.createActivityReport("ActivityReport.pdf", start, end);
		rb.createOperationReport("OperationReport.pdf", start, end);
		rb.createOperationReport("DelayReport.pdf", start, end);


	  
	}


	public double deviation(Map<Integer, Double> map) 
	{
		if (map.size() >0 )
		{
			//TreeMap<Integer,Double> srtdMap = new TreeMap<Integer,Double>(map);
			int n = map.values().size();
			double average = avaregeDouble(map);
			System.out.println("average in report: "+average );
			System.out.println("n in report: "+n );
			double squareSum = 0;
			for (Double d : map.values() )
			{
				squareSum += (d-average)*(d-average);
			}
			
			double deviation = Math.sqrt(squareSum/n);
	
			
			return deviation;
		}
		 return 0;
	}
	
	private double deviationInt(Map<Integer, Integer> map)
	{
		if (map.size() >0 )
		{
			//TreeMap<Integer,Double> srtdMap = new TreeMap<Integer,Double>(map);
			int n = map.values().size();
			double average = avarege(map);
			double squareSum = 0;
			for (Integer i : map.values() )
			{
				squareSum += (i-average)*(i-average);
			}
			
			double deviation = Math.sqrt(squareSum/n);
	
			
			return deviation;
		}
		 return 0;
	}



}
